package com.fellansoft.moviescollection.activities;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.widget.*;
import com.fellansoft.moviescollection.R;
import com.fellansoft.moviescollection.business.BusinessConstants;
import com.fellansoft.moviescollection.business.DataManager;
import com.fellansoft.moviescollection.data.CoverFlowElement;
import com.fellansoft.moviescollection.data.CoverFlowFolder;
import com.fellansoft.moviescollection.gui.CoverFlow;
import com.fellansoft.moviescollection.gui.ImageAdapter;
import com.fellansoft.moviescollection.utils.ActivityUtils;
import com.fellansoft.moviescollection.utils.ApplicationVariables;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity
{
    /**
     * The application context used to register receivers
     */
    private Context context;
    /*
     * The spinner for showing that the program is still working
     */
    private Spinner groupBySpinner;

    private CoverFlow coverFlow;
    /*
     * Edit Text for the search box
     */
    private EditText searchEditText;
    /*
     * Text View for search box
     */
    private TextView labelTextView;

    private ImageAdapter coverImageAdapter;
    /*
     * CoverFlow List of elements
     */
    private List<CoverFlowElement> elems;
    /*
     * Coverflow List of folders
     */
    private List<CoverFlowElement> folders;
    /*
     * Custom button for back
     */
    private Button backButton;
    /*
     * Toggle Button for search
     */
    private ToggleButton searchToggleButton;

    boolean showingFolders;
    boolean showingSearchResult = false;
    int oldCategory;
    String lastFolder;

    /**
     * Intent filter for the intents sent when the folders were received from database
     */
    private IntentFilter receivedFoldersSuccessIntentFilter;

    /**
     * Intent filter for the intents sent when the movies were received from database
     */
    private IntentFilter receivedMoviesSuccessIntentFilter;

    /**
     * Intent filter for the intents sent when there was a problem receiving folders from database
     */
    private IntentFilter receiveFoldersErrorIntentFilter;

    /**
     * Intent filter for the intents sent when there was a problem receiving movies from database
     */
    private IntentFilter receiveMoviesErrorIntentFilter;

    /**
     * Receiver for the intents sent when the folders were received successfully
     */
    private BroadcastReceiver receiveFoldersSuccessReceiver;

    /**
     * Receiver for the intents sent when the movies were received successfully
     */
    private BroadcastReceiver receiveMoviesSuccessReceiver;

    /**
     * Receiver for the intents sent when there was a problem receiving folders from database
     */
    private BroadcastReceiver receiveFoldersErrorReceiver;

    /**
     * Receiver for the intents sent when there was a problem receiving movies from database
     */
    private BroadcastReceiver receiveMoviesErrorReceiver;

    private IntentFilter getMovieByIdSuccessIntentFilter;
    /*
     * Receiver for the intents sent by their successRecevier
     */
    private BroadcastReceiver getMovieByIdSuccessReceiver;
    /*
     *  Intent filter for the intents sent when there was a problem with the intent filter
     */
    private IntentFilter getMovieByIdErrorIntentFilter;
    /*
     * Receiver for the intents sent by the errorReceiver
     */
    private BroadcastReceiver getMovieByIdErrorReceiver;
    /*
     *  Intent filter for the intents sent when there was a success received with the intentFilter
     */
    private IntentFilter getMoviesFromSearchSuccessIntentFilter;
    /*
     * Receiver for the intents sent when there was a success receiving movies from database
     */
    private BroadcastReceiver getMoviesFromSearchSuccessReceiver;
    /*
     *  Intent filter for the intents sent when there was a problem receiving folders from database
     */
    private IntentFilter getMoviesFromSearchErrorIntentFilter;
    /*
     *  Receiver for the intents sent when there was a problem receiving movies from database
     */
    private BroadcastReceiver getMoviesFromSearchErrorReceiver;
    /*
     * Value for year picker Catalog
     */
    private final int ADD_MOVIE = 1192;
    /*
     * Value for year picker Catalog
     */
    private final int VIEW_MOVIE = 1193;
    /*
     *  Value initialised for FolderRefresh
     */
    private boolean needsFoldersRefresh = false;


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        setTheme(android.R.style.Theme_Holo);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        setContentView(R.layout.main);

        context = getApplicationContext();

        backButton = (Button)findViewById(R.id.buttonBack);
        searchToggleButton = (ToggleButton)findViewById(R.id.buttonSearch);

        ApplicationVariables.setApplicationContext(context);
        
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);

        ApplicationVariables.setDisplayWidth(metrics.widthPixels);

        switch (metrics.densityDpi) {
		case DisplayMetrics.DENSITY_HIGH:
            ApplicationVariables.setDisplayHeight(metrics.heightPixels-48);
			break;
		case DisplayMetrics.DENSITY_MEDIUM:
            ApplicationVariables.setDisplayHeight(metrics.heightPixels-32);
		case DisplayMetrics.DENSITY_LOW:
            ApplicationVariables.setDisplayHeight(metrics.heightPixels-24);
		default:
			break;
		}

        int h = 0 ;
        int w = 0 ;

        switch (metrics.densityDpi) {
		case DisplayMetrics.DENSITY_HIGH:
            h = ApplicationVariables.getDisplayHeight() / 2;
            w = ApplicationVariables.getDisplayWidth() * 9 / 48;
			break;
		case DisplayMetrics.DENSITY_MEDIUM:
            h = ApplicationVariables.getDisplayHeight() * 2 / 5;
            w = ApplicationVariables.getDisplayWidth() * 9 / 48;
            break;
		case DisplayMetrics.DENSITY_LOW:
            h = ApplicationVariables.getDisplayHeight() / 2;
            w = ApplicationVariables.getDisplayWidth() * 9 / 48;
            break;
		default:
			break;
		}

        groupBySpinner = (Spinner)findViewById(R.id.groupBySpinner);
        coverFlow = (CoverFlow)findViewById(R.id.coverflow);
        searchEditText = (EditText)findViewById(R.id.searchEditText);
        labelTextView = (TextView)findViewById(R.id.labelTextView);

        if (elems == null)
            elems = new ArrayList<CoverFlowElement>();

        if (coverImageAdapter == null)
        {
            coverImageAdapter = new ImageAdapter(this,elems);
            coverImageAdapter.setLayoutParams(w,h);
            coverImageAdapter.createReflectedImages();
            coverFlow.setAdapter(coverImageAdapter);
        }

        //coverFlow.setSpacing(0);
        coverFlow.setMaxRotationAngle(85);
        coverFlow.setMaxZoom(-300);
        coverFlow.setAnimationDuration(1000);

        createListeners();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && searchEditText.getVisibility() == View.VISIBLE) {
            searchEditText.setVisibility(View.INVISIBLE);
            searchToggleButton.toggle();
            return true;
        }
        if ((keyCode == KeyEvent.KEYCODE_BACK) && !showingFolders) {
            backToFolders(null);
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * Set listeners for widgets
     */
    private void createListeners()
    {
        coverFlow.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
            {
                if (((CoverFlowElement)coverImageAdapter.getItem(position)).getLabel() != null)
                    labelTextView.setText(((CoverFlowElement)coverImageAdapter.getItem(position)).getLabel());
                else
                    labelTextView.setText("Position: "+position);
            }

            public void onNothingSelected(AdapterView<?> adapterView) {
                //labelTextView.setText("Nothing selected ");
            }
        });


       coverFlow.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            public void onItemClick(final AdapterView< ? > parent, final View view, final int position, final long id) {
                //Toast.makeText(MainActivity.this,"Item clicked! : " + id,Toast.LENGTH_SHORT).show();
                if (showingSearchResult)
                    requestMovieById(((CoverFlowElement)(coverImageAdapter.getItem(position))).getId());
                else if (showingFolders)
                {
                    showingFoldersItIs(false);
                    folders = new ArrayList<CoverFlowElement>(elems);
                    if (oldCategory == 0)
                        requestMovies(String.valueOf
                                (indexForGenre(((CoverFlowFolder)coverImageAdapter.getItem(position)).getLabel())));
                    else
                        requestMovies(((CoverFlowFolder) (coverImageAdapter.getItem(position))).getLabel());
                }
                else
                {
                    requestMovieById(((CoverFlowElement)(coverImageAdapter.getItem(position))).getId());
                }
            }
        });

        groupBySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                requestFolders(pos);
            }

            public void onNothingSelected(AdapterView parent) {
                // do nothing
            }
        });

        searchEditText.setOnKeyListener(new View.OnKeyListener() {
            public boolean onKey(View view, int i, KeyEvent keyEvent) {
                if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER && KeyEvent.ACTION_UP == keyEvent.getAction())
                    search();
                return false;  //To change body of implemented methods use File | Settings | File Templates.
            }
        });
    }

    /**
     * Find out a genre's index in genres array
     * @param genre
     * @return The seeked value
     */
    private int indexForGenre(String genre)
    {
        String[] genres = ApplicationVariables.getApplicationContext().getResources().getStringArray(R.array.Categories);
        for (int i=0; i< genres.length; i++)
            if (genres[i].equalsIgnoreCase(genre))
                return i;
        return -1;
    }

    /**
     * Retrieve movie search results
     */
    private void search()
    {
        String s = searchEditText.getText().toString();
        if (s.length() == 0)
            return;

        ActivityUtils.showProgressDialog(MainActivity.this);

        if (getMoviesFromSearchSuccessIntentFilter == null)
            getMoviesFromSearchSuccessIntentFilter = new IntentFilter(BusinessConstants.BC_MOVIES_FROM_SEARCH_SUCCESSFULLY);
        if (getMoviesFromSearchSuccessReceiver == null)
            getMoviesFromSearchSuccessReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context localContext, Intent intent) {
                    context.unregisterReceiver(getMoviesFromSearchSuccessReceiver);
                    coverImageAdapter.clearElements();
                    coverImageAdapter.setNewListOfElement(DataManager.getInstance().getMoviesList());
                    showingSearchResult = true;
                    if (coverImageAdapter.getCount() > 0)
                    {
                        coverFlow.setSelection(0,false);
                        labelTextView.setText(((CoverFlowElement)coverImageAdapter.getItem(0)).getLabel());
                    }
                    else
                        labelTextView.setText("No movies!");
                    ActivityUtils.hideProgressDialog(MainActivity.this);
                }
            };
        context.registerReceiver(getMoviesFromSearchSuccessReceiver,getMoviesFromSearchSuccessIntentFilter);

        DataManager.getInstance().searchMovies(s);

        ActivityUtils.hideProgressDialog(MainActivity.this);
    }

    /**
     * Retrive a movie by id
     * @param id Movie's id
     */
    private void requestMovieById(int id)
    {
        ActivityUtils.showProgressDialog(MainActivity.this);

        if (getMovieByIdSuccessIntentFilter == null)
            getMovieByIdSuccessIntentFilter = new IntentFilter(BusinessConstants.BC_MOVIES_GETBYID_SUCCESSFULLY);
        if (getMovieByIdSuccessReceiver == null)
            getMovieByIdSuccessReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context localContext, Intent intent) {
                    context.unregisterReceiver(getMovieByIdSuccessReceiver);

                    ActivityUtils.hideProgressDialog(MainActivity.this);

                    Intent intentView = new Intent(MainActivity.this, ViewMovie.class);
                    startActivityForResult(intentView,VIEW_MOVIE);
                }
            };
        context.registerReceiver(getMovieByIdSuccessReceiver,getMovieByIdSuccessIntentFilter);

        DataManager.getInstance().getMovieById(Long.valueOf(id));
    }

    /**
     * Retrieve movies from a folder
     * @param param Movie identifier
     */
    private void requestMovies(String param)
    {
        lastFolder = param;
        showingSearchResult = false;
        ActivityUtils.showProgressDialog(MainActivity.this);
        showingFoldersItIs(false);
        if (receivedMoviesSuccessIntentFilter == null)
            receivedMoviesSuccessIntentFilter = new IntentFilter(BusinessConstants.BC_MOVIES_RECEIVED_SUCCESSFULLY);
        if (receiveMoviesSuccessReceiver == null)
            receiveMoviesSuccessReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context localContext, Intent intent) {
                    context.unregisterReceiver(receiveMoviesSuccessReceiver);
                    coverImageAdapter.clearElements();
                    coverImageAdapter.setNewListOfElement(DataManager.getInstance().getMoviesList());
                    if (coverImageAdapter.getCount() > 0)
                    {
                        coverFlow.setSelection(0,false);
                        labelTextView.setText(((CoverFlowElement)coverImageAdapter.getItem(0)).getLabel());
                    }
                    else
                        labelTextView.setText("No movies!");
                    ActivityUtils.hideProgressDialog(MainActivity.this);
                }
            };
        context.registerReceiver(receiveMoviesSuccessReceiver,receivedMoviesSuccessIntentFilter);

       ApplicationVariables.RequestMoviesTypes type = null;

        //Make the request
        switch (this.oldCategory)
        {
            case 0:
                type = ApplicationVariables.RequestMoviesTypes.GENRES;
                break;
            case 1:
                type = ApplicationVariables.RequestMoviesTypes.ALPHABETICALLY;
                break;
            case 2:
                type = ApplicationVariables.RequestMoviesTypes.RELEASE_YEAR;
                break;
            case 3:
                type = ApplicationVariables.RequestMoviesTypes.COLLECTIONS;
                break;
        }

        DataManager.getInstance().requestMoviesInsideFolder(type,param);
    }

    private void requestFolders(int which)
    {
        showingSearchResult = false;
        ActivityUtils.showProgressDialog(MainActivity.this);
        this.oldCategory = which;
        showingFoldersItIs(true);
        if (receivedFoldersSuccessIntentFilter == null)
            receivedFoldersSuccessIntentFilter = new IntentFilter(BusinessConstants.BC_FOLDERS_RECEIVED_SUCCESSFULLY);
        if (receiveFoldersSuccessReceiver == null)
            receiveFoldersSuccessReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context localContext, Intent intent) {
                    context.unregisterReceiver(receiveFoldersSuccessReceiver);
                    coverImageAdapter.clearElements();
                    elems = DataManager.getInstance().getMoviesList();
                    coverImageAdapter.setNewListOfElement(elems);
                    if (coverImageAdapter.getCount() > 0)
                    {
                        coverFlow.setSelection(0,false);
                        labelTextView.setText(((CoverFlowElement)coverImageAdapter.getItem(0)).getLabel());
                    }
                    else
                        labelTextView.setText("No folders!");
                    ActivityUtils.hideProgressDialog(MainActivity.this);
                }
            };
       context.registerReceiver(receiveFoldersSuccessReceiver,receivedFoldersSuccessIntentFilter);

       ApplicationVariables.RequestMoviesTypes type = null;

        //Make the request
        switch (which)
        {
            case 0:
                type = ApplicationVariables.RequestMoviesTypes.GENRES;
                break;
            case 1:
                type = ApplicationVariables.RequestMoviesTypes.ALPHABETICALLY;
                break;
            case 2:
                type = ApplicationVariables.RequestMoviesTypes.RELEASE_YEAR;
                break;
            case 3:
                type = ApplicationVariables.RequestMoviesTypes.COLLECTIONS;
                break;
        }

        DataManager.getInstance().requestMovies(type);
    }

    private void showingFoldersItIs(boolean isIt)
    {
        showingFolders = isIt;

        if (isIt)
        {
            backButton.setVisibility(View.INVISIBLE);
            showingSearchResult = false;
        }
        else
        {
            backButton.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    public void searchButtonClicked(View view)
    {
        if (searchEditText.getVisibility() == View.VISIBLE)
            this.searchEditText.setVisibility(View.INVISIBLE);
        else
            this.searchEditText.setVisibility(View.VISIBLE);
    }

    public void addMovie(View view)
    {
        Intent intent=new Intent(MainActivity.this,AddMovie.class);
        this.startActivityForResult(intent, ADD_MOVIE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
        super.onActivityResult(requestCode, resultCode, imageReturnedIntent);

        switch (requestCode) {
            case ADD_MOVIE:
                if (resultCode == RESULT_OK) {
                    reloadCoverFlow();
                }
                break;
            case VIEW_MOVIE:
                if (resultCode == RESULT_OK) {
                    reloadCoverFlow();
                }
                break;
        }
    }

    private void reloadCoverFlow()
    {
        if (showingFolders)
            requestFolders(this.oldCategory);
        else
        {
            requestMovies(this.lastFolder);
            this.needsFoldersRefresh = true;
        }
    }

    public void backToFolders(View view)
    {
        if (this.needsFoldersRefresh)
        {
            this.needsFoldersRefresh = false;
            requestFolders(this.oldCategory);
        }
        else
        {
            elems = new ArrayList<CoverFlowElement>(folders);
            coverImageAdapter.setNewListOfElement(elems,false);
            if (coverImageAdapter.getCount() > 0)
            {
                coverFlow.setSelection(0,false);
                labelTextView.setText(((CoverFlowElement)coverImageAdapter.getItem(0)).getLabel());
            }
            else
                labelTextView.setText("No folders!");
            showingFoldersItIs(true);
        }
    }
}
